//  类似java 的接口


//1。 定义一个trait


use std::fmt::{Display, format};

pub trait Summary {
    fn summarize1(&self) -> String;
    fn summarize2(&self) -> String;

    // 默认实现
    fn summarize3(&self) -> String {
        String::from("read More")
    }


    // 在默认实现中可以调用 没有默认实现的方法
    fn summarize4(&self) -> String {
        self.summarize1()
    }
}

//2.  在类型上实现trait


pub struct News {
    pub title: String,
    pub location: String,
    pub author: String,
    pub context: String,

}


// 实现trait
impl Summary for News {
    // 实现trait 的方法
    fn summarize1(&self) -> String {
        format!("{}, by {}  ({})", self.title, self.author, self.location)
    }

    fn summarize2(&self) -> String {
        format!("{}, by {}  ---- ({})", self.title, self.author, self.location)
    }

    //    summarize3 可以不实现
    fn summarize3(&self) -> String {
        String::from("新的summarize3")
    }
}


#[test]
fn test_trait() {
    let new = News {
        title: "111".to_string(),
        author: "tom".to_string(),
        context: "3333333333333".to_string(),
        location: "上海".to_string(),
    };


    let sum1 = new.summarize1();
    let sum2 = new.summarize2();
    println!("sum1 is {} , sum2 is {}", sum1, sum2);


    let sum3 = new.summarize3();
    let sum4 = new.summarize4();
    println!("sum3 is {} , sum3 is {}", sum3, sum4);
}


//  trait 作为函数的参数
/*
1. impl Trait
2. Trait bound   针对复杂的情况
3. 指定多个trait
4. where 指定trait的约束


*/

//1.  impl Trait
fn notify1(sum1: impl Summary, sum2: impl Summary) {
    println!("sum is {}", sum1.summarize1())
}


//2. Trait bound
fn notify2<T: Summary>(sum1: T, sum2: T) {
    println!("sum is {}", sum1.summarize1())
}

// 3.多个trait

fn notify3(sum1: impl Summary, sum2: impl Summary + Display) {
    println!("sum is {}", sum1.summarize1())
}

fn notify4<T: Summary + Display>(sum1: T, sum2: T) {
    println!("sum is {}", sum1.summarize1())
}


// 4. where 约束

fn notify5<T, U>(sum1: T, sum2: U) -> String
    where T: Summary + Display,
          U: Summary + Clone
{
   "".to_string()
}




// trait 作为返回值
